require("SOD/StructureGenerator/StructureGenerator")

module SOD
  
  OPT_STATUS_STOPED   = -1
  OPT_STATUS_RUNNING  = 0
  OPT_STATUS_FINISHED = 1

  class StructureGeneratorData
    
    attr_accessor :bars, :slt_bars, :default_bar, :active_bar, \
                  :my_database_path, :dialog, :cppBar, \
                  :db_is_ready
    
    def initialize
      #structure_generator_dir = Plugin.dir + "/StructureGenerator"
      structure_generator_dir = Sketchup.find_support_file "StructureGenerator", "Plugins/SOD"
      @cppBar = StructureGenerator::BuildingBar.new(structure_generator_dir)
      init_bars
      
    end

    def init_bars
      @bars = Array.new
      @slt_bars = Array.new
    end


    def update(sghash)
    end

    # def update_bar_by_model( rb_bar = @active_bar )
    #   rb_bar[:fp_wdt] = Plugin.model.sketchInfoContainer.footprintWidth.to_m.to_f
    #   rb_bar[:fp_lng] = Plugin.model.sketchInfoContainer.footprintLength.to_m.to_f
    #   rb_bar[:fx_hgh] = Plugin.model.projectInfo.minConstructionHeight #? \
    #     # Plugin.model.projectInfo.minConstructionHeight.to_mm.to_i : 300# flexibility height
    #   rb_bar[:n_stys] = Plugin.model.projectInfo.numberOfStoreys # number of storeys
    #   # rb_bar[:clzn_r] = []
    #   puts "rb_bar[:fp_wdt] - " + rb_bar[:fp_wdt].to_s
    #   puts "rb_bar[:fp_lng] - " + rb_bar[:fp_lng].to_s
    # end
    
    # def update_selected_by_hash(h)
    #   return nil if !(h.is_a? Hash)
    #   h.each {|key, value| 
    #     @active_bar[key] = value
    #     @slt_bars.each{ |idx| 
    #       @bars[idx][key] = value
    #     }    
    #   }
    # end

    # def update_selected_by_value(key,value)
    #   return if !@active_bar.has_key? key   
    #   @active_bar[key] = value
    #   @slt_bars.each{ |idx| 
    #       return if !@bars[idx].has_key? key   
    #       @bars[idx][key] = value
    #   }    
    # end

    # def add_bar(h)
    #   return nil if !(h.is_a? Hash)
    #   bar = new_default_bar
    #   h.each {|key, value| 
    #     return if !bar.has_key? key
    #     bar[key] = value
    #   }
    #   @bars.push(bar)
    # end

    # def select(idx)
    #   if idx.is_a? Integer
    #     return if @slt_bars.include? idx
    #     @slt_bars.push idx
    #   elsif idx.is_a? String
    #     sel = nil
    #     idx = idx.to_sym
    #     @bars.each_index{ |h| 
    #       sel = h if idx == @bars[h][:bar_id] 
    #     }
    #     return if @slt_bars.include? sel
    #     @slt_bars.push sel
    #   elsif idx.is_a? Symbol
    #     sel = nil
    #     @bars.each_index{ |h| 
    #       sel = h if idx == @bars[h][:bar_id] 
    #     }
    #     return if @slt_bars.include? sel
    #     @slt_bars.push sel
    #   else
    #     nil
    #   end
    # end


    def read_database( rb_bar = nil)
      path = Plugin.dir + "/StructureGenerator/"
      @my_database_path = UI.openpanel("Read Database", path, ".txt")
      if @my_database_path.nil?
        # puts "rb_bar[:db_rdy] - no path returned!" #Fabian
        puts "db_is_ready - no path returned!" #Fabian
        return
      else
        puts "my_database_path:"
        puts @my_database_path.to_s
        @db_is_ready = @cppBar.ReadDateBase(@my_database_path.to_s) 
        puts "db_is_ready - " + db_is_ready.to_s
        # rb_bar[:db_rdy] = db_is_ready if rb_bar
      end
    end

    def draw_in_tekla( rb_bar = nil)

      if rb_bar.nil?
        puts "rb_bar : nil  - no selection!" 
        return
      end
      puts "draw_in_tekla"

      # barInfo = @cppBar.GetBarRef()
      # gaResult = StructureGenerator::GaResult.new
      # StructureGenerator::BuildingBar::ConvertGaGenesToGaResult(barInfo, gaResult)
      # puts gaResult.nofStoreys;

      res = @cppBar.DrawInTekla()
      puts "@cppBar.DrawInTekla()"
      puts res
    end
    

    def update_by_gene_string ( rb_bar = nil, cpp_bar = nil )
      return false if !rb_bar or ! cpp_bar
      rb_bar[:opt_st] = @cppBar.OptStatus()
      rb_bar[:gn_str] = @cppBar.Genes_string()
      
      rb_bar[:fitnss] = @cppBar.Fitness()
      rb_bar[:ps_col] = rb_bar[:clzn_r][0].to_f + rb_bar[:gn_str][0].to_i * @cppBar.Step_COL().to_f

      # puts "@cppBar.IsOptFinished()"
      puts "g_opt_status #{rb_bar[:opt_st]}"
      puts (rb_bar[:gn_str].map { |s| s.to_i }).join(",")
      puts rb_bar[:fitnss]
      puts rb_bar[:ps_col]


      fit  = rb_bar[:fitnss]
      gArr = rb_bar[:gn_str]
      pstn = rb_bar[:ps_col]

      bm_hgh_2nd = Plugin.sgdata.cppBar.SectionHeight( Integer(rb_bar[:gn_str][4]) )
      bm_hgh_1st = Plugin.sgdata.cppBar.SectionHeight( Integer(rb_bar[:gn_str][6]) )
      rb_bar[:bm_hgh] = bm_hgh_2nd > bm_hgh_1st ? bm_hgh_2nd : bm_hgh_1st
      puts "rb_bar[:bm_hgh]: " + rb_bar[:bm_hgh].to_s
      rb_bar[:sl_hgh] = rb_bar[:gn_str][3]
      puts "rb_bar[:sl_hgh]: " + rb_bar[:sl_hgh].to_s


      rb_bar[:g_r_vc] = @cppBar.Concrete()
      rb_bar[:g_r_mr] = @cppBar.ReinforcementSteel()
      rb_bar[:g_r_mp] = @cppBar.ProfiledSheeting()
      rb_bar[:g_r_mq] = @cppBar.StrctureSteel()
      rb_bar[:g_r_aa] = @cppBar.SteelCoating()
      puts "rb_bar[:g_r_vc]: ", rb_bar[:g_r_vc]
      puts "rb_bar[:g_r_mr]: ", rb_bar[:g_r_mr]
      puts "rb_bar[:g_r_mp]: ", rb_bar[:g_r_mp]
      puts "rb_bar[:g_r_mq]: ", rb_bar[:g_r_mq]
      puts "rb_bar[:g_r_aa]: ", rb_bar[:g_r_aa]


      osg_message = ""
      if @cppBar.HasSolution() 

        osg_message = "<h3>Carbon Dioxide Equivalent(CDE) :&nbsp;&nbsp;" + format("%.2f", fit.to_f) + " kg</h3><br/>"
        osg_message += "<table><tbody>"
        osg_message += "<tr><td>Inner Column Position:</td>"
        osg_message += "<td>"+format("%.1f", pstn.to_f) + "</td></tr>"
        osg_message += "<tr><td>Number of Column in Row:"
        osg_message += "<td>"+(2 + gArr[1].to_i).to_s  + "</td></tr>"

        if 0 == gArr[8]
        osg_message += "<tr><td>Primary Beams' Direction:</td><td>transverse</td>"
        osg_message += "<tr><td>Number of Secondary Beams in Span:</td><td>"+ (gArr[10].to_i).to_s  + "</td></tr>"
        osg_message += "<tr><td>Width of Secondary Beam:</td><td>"+ format("%.2f", (( rb_bar[:fp_wdt].to_f)/(gArr[10].to_i-1).to_f))  + "</td></tr>"
        # puts format("%.2f", (( w_int.to_f)/(gArr[10].to_i-1).to_f))
        else
        osg_message += "<tr><td>Primary Beams' Direction:</td><td>longitudinal</td>"
        osg_message += "<tr><td>Number of Secondary Beams in Span:</td><td>"+ (gArr[10].to_i).to_s  + "</td></tr>"
        osg_message += "<tr><td>Width of Secondary Beam:</td><td>"+ format("%.2f", (( rb_bar[:fp_lng].to_f)/(gArr[10].to_i-1).to_f))  + "</td></tr>"
        end
        osg_message += "<tr><td>2nd:&nbsp;&nbsp;" + StructureGenerator::BuildingBar::SectionName(gArr[4].to_i).to_s 
        osg_message += "&nbsp;-&nbsp;S"+gArr[5].to_i.to_s + "</td><td>"
        osg_message += "1st:&nbsp;&nbsp;" + StructureGenerator::BuildingBar::SectionName(gArr[6].to_i).to_s 
        osg_message += "&nbsp;-&nbsp;S"+gArr[7].to_i.to_s + "</td></tr>"
        i = 0

        while i < rb_bar[:n_stys].to_i  do
          osg_message += "<tr><td>(&nbsp;" +StructureGenerator::BuildingBar::SectionName(gArr[11+i*4]) 
          osg_message += "&nbsp;-&nbsp;S"+gArr[12+i*4].to_i.to_s + ")</td><td>";
          osg_message += "(&nbsp;" +StructureGenerator::BuildingBar::SectionName(gArr[13+i*4]) 
          osg_message += "&nbsp;-&nbsp;S"+gArr[14+i*4].to_i.to_s + "&nbsp;)</td></tr>";
          i +=1;
        end
        osg_message += "</tbody></table>"
        osg_message += "</p>"
      else
        osg_message = "<h3>no solution<h3><br/>"
      end
      puts "<h3>Carbon Dioxide Equivalent(CDE) :&nbsp;&nbsp;" + format("%.2f", fit.to_f) + " kg</h3><br/>"
      dialog.updata_sg_message( osg_message ) if dialog
    end

    def run_generator( rb_bar = nil)

      if rb_bar.nil?
        puts "rb_bar : nil  - no selection!" 
        osg_message = "<h3>nothing selected</h3>"
        if dialog 
          dialog.updata_sg_message( osg_message )
        end
        return
      end
      
      if !(@db_is_ready)
        puts "db_is_ready: ", db_is_ready.to_s
        osg_message = "<h3>database not ready</h3>"
        if dialog 
          dialog.updata_sg_message( osg_message )
        end
        return
      end

      # update_bar_by_model
      # update

      return if ( rb_bar[:fp_lng] == 0 and rb_bar[:fp_wdt]  = 0 )
      
        puts "-------start run gengerator -----------"
        puts "Start at #{Time.now}"
      
        l = (rb_bar[:fp_lng]*1000).round.to_i;
        w = (rb_bar[:fp_wdt]*1000).round.to_i;    
        construtHeight = (rb_bar[:co_hgh]).round.to_i;  
        # nof_storeys = rb_bar[:n_stys]
        puts "l:" + l.to_s;
        puts "w:" + w.to_s;

        l_int = Integer(l)
        w_int = Integer(w)
        puts "l_int:" + l_int.to_s;
        puts "w_int:" + w_int.to_s;

        @cppBar.Length(l_int)
        @cppBar.Width(w_int)

        # Plugin.model.projectInfo.update_values
        storey_hight = rb_bar[:fx_hgh] \
        + rb_bar[:rm_hgh] \
        + construtHeight
        @cppBar.FloorHeight(Integer(storey_hight/10.0));


        
        puts " ------ my_bar -------"
        @cppBar.ConstrutHeight( construtHeight)
        @cppBar.No_of_stories(  rb_bar[:n_stys])
        @cppBar.PopulationSize( rb_bar[:p_size]);
        @cppBar.NofGenerations( rb_bar[:nof_gn]);
        @cppBar.MutationProbability(  rb_bar[:p_muta] );
        @cppBar.CrossoverProbability( rb_bar[:p_crss] );

        @cppBar.X_COL( rb_bar[:clzn_r][0].to_f );
        @cppBar.Y_COL( rb_bar[:clzn_r][1].to_f );
        
        cpp_l = @cppBar.Length()
        cpp_w = @cppBar.Width()
        puts cpp_l
        puts cpp_w
        puts @cppBar.FloorHeight().to_s
        puts @cppBar.ConstrutHeight().to_s
        puts @cppBar.No_of_stories().to_s
        puts @cppBar.PopulationSize().to_s
        puts @cppBar.NofGenerations().to_s
        puts @cppBar.MutationProbability().to_s
        puts @cppBar.CrossoverProbability().to_s
        puts @cppBar.X_COL().to_s
        puts @cppBar.Y_COL().to_s

        cl_sps_arr = Array(rb_bar[:cl_sps])
        if cl_sps_arr.empty? == 0
          dialog.updata_sg_message( "<h3>No Possible Spacing</h3>" ) if dialog
          return 
        end
        puts "Array(rb_bar[:cl_sps]).length: " + cl_sps_arr.length.to_s
        puts "Array(rb_bar[:cl_sps]): " + cl_sps_arr.to_s
        cpp_clsps_vec = StructureGenerator::IntVector.new( cl_sps_arr.length);
        0.upto(cpp_clsps_vec.size-1) { |i| cpp_clsps_vec[i] = cl_sps_arr[i] }
        @cppBar.PossibleSpacing(cpp_clsps_vec)
        
        print 'cl_sps_vec: '
        0.upto(cpp_clsps_vec.size-1) { |i| print cpp_clsps_vec[i],"; " }
        print "\n"
        
        puts "cl_sps_vec.length:"
        puts cpp_clsps_vec.size
        if cpp_clsps_vec.size == 0
          dialog.updata_sg_message( "<h3>No Possible Spacing</h3>" ) if dialog
          return 
        end

        dircts_arr = Array(rb_bar[:dircts])
        if dircts_arr.empty? == 0
          dialog.updata_sg_message( "<h3>No Possible Direction</h3>" ) if dialog
          return 
        end

        puts "Array(rb_bar[:dircts]).length: " + dircts_arr.length.to_s
        puts "Array(rb_bar[:dircts]): " + dircts_arr.to_s
        cpp_dircts_vec = StructureGenerator::IntVector.new( dircts_arr.length);
        0.upto(cpp_dircts_vec.size-1) { |i| cpp_dircts_vec[i] = dircts_arr[i] }
        @cppBar.PossibleDirections(cpp_dircts_vec)
        
        print 'cl_sps_vec: '
        0.upto(cpp_dircts_vec.size-1) { |i| print cpp_dircts_vec[i],"; " }
        print "\n"
        
        puts "cl_sps_vec.length:"
        puts cpp_dircts_vec.size
        if cpp_dircts_vec.size == 0
          dialog.updata_sg_message( "<h3>No Possible Direction</h3>" ) if dialog
          return 
        end
        
        puts @cppBar.Length()
        puts @cppBar.Width()
        puts @cppBar.ConstrutHeight()
        puts @cppBar.No_of_stories()

        puts @cppBar.CurrentDirectory()

        osg_message = "<h3>Running...</h3>"
        if dialog 
          dialog.updata_sg_message( osg_message )
        end

        rb_bar[:opt_st] = OPT_STATUS_RUNNING
        @cppBar.OptStatus(OPT_STATUS_RUNNING)

        @cppBar.RunGenerator()

        thread = Thread.new{
          sleep(0.1)
          run_time = 0.0
          time_step = 0.04
          id = 0;
          id_check = (0.1/0.04).to_i 
          puts "id_check"
          puts id_check
          while run_time < 30.0
            run_time += time_step
            id += 1
            sleep(0.04)
            puts id
            break if OPT_STATUS_FINISHED == @cppBar.OptStatus()
            # # if id%id_check == 0
            #   puts id/id_check 
            #   js_command = "passFromRubyToJsUpdateTimeIconById(\""+ id/id_check + "\")"
            #   puts js_command
            #   $g_my_dialog.execute_script(js_command)
            # # end
          end

          puts "End at #{Time.now}"

          update_by_gene_string(rb_bar, @cppBar)
          
        }

        Sketchup.send_action("Run_Structure_Generator:")

    end
    
  end
  
end
